import os,glob,sys,string
from ini import ini_file
from common import *
from gamemap import *
##from Numeric import *

class MapLoader:
    class Error(Exception):
        pass
    def __init__(self,map_path):
        self.map_path = map_path
        map_ini_files = self._getAllMaps(map_path)
        maps = {}
        for map_ini in map_ini_files:
            try:
                map_setting =(self.__getMapSettings(map_ini))
                maps[map_setting['name']] = map_setting
            except Exception,errmsg:
                raise SystemExit(errmsg)

        self.maps = maps
        
    def getAllMapNames(self):
        return self.maps.keys()#.sort()

    def getGameMap(self,name):
        self.__createLayerMaps(name)
        return self.layers[0]

    def getTiledLayer(self,parallax_layers):
        ' create a TiledLayer(Drawable) object from the map '
        fg_layer = TiledLayer(self.layers[0])

        if parallax_layers == 1 or parallax_layers == 3:
            background_layer = TiledLayer(self.layers[2])
            # link scroll layers together
            fg_layer.link(background_layer, 0.25)
        if parallax_layers == 2 or parallax_layers == 3:
            middle_layer = TiledLayer(self.layers[1])
            fg_layer.link(middle_layer, 0.5)
        return fg_layer        

    def __getMapSettings(self,map_file):
        ' build a map setting dict from the map ini file '
        map_ini = ini_file(map_file)
        m = map_ini
        name = m['Map']['Name']
        bg=string.split(m['Map']['BgColor'],",")
        bgcolor =( int(bg[0]),int(bg[1]),int(bg[2]) ) 

        
        maxplayers = int(m['Map']['MaxPlayers'])
        # SetUp Players Starting Positions
        startingPos = []
        for nr in range(1,maxplayers+1):
            nr = "%d"%nr
            pos=string.split(m['PlayersStartPos'][nr],",")
            startingPos+=((int(pos[0]),int(pos[1])),) 

        # Create the bases array to use from the map file
        try:
            gameBases = []
            for base in m['Bases'].keys():
                # Create an base object and append it to bases list
                tile_types = []
                for tile_type in string.split(m['Bases'][base],","):
                    tile_types.append(int(tile_type))
                gameBases.append(apply(eval(base),(tile_types,)))

        except Exception,errmsg:
            sys.stderr.write('Error setting up bases from file %s\n'%map_file)
            raise

        # creat main game map
        map_path = os.path.split(map_file)[0]

        layers = [ m[m['Map']['GameMap']] , m[m['Map']['Middle']] , m[m['Map']['Back']] ]
        
        path = os.path.split(map_file)[0]
        map_settings = {'name':name,'bases':gameBases,'maxplayers':maxplayers,'startpos':startingPos, 'layers':layers,'path':path,'bgcolor':bgcolor}
        return map_settings

    def _getAllMaps(self,path):
        ' get all the map ini files avaible '
        maps = []
        for dir in os.listdir(path):
            dir = os.path.join(path,dir)
            if not os.path.isdir(dir):
                continue
            map_inifiles = glob.glob(os.path.join(dir,'*.ini'))
            if map_inifiles:
                for ini in map_inifiles:
                    maps.append(ini)
        return maps

    def __createLayerMaps(self,name):
        error = self.__class__.Error
        try:        
            map_settings = self.maps[name]
        except KeyError,errmsg:
            raise error('Error: No map named:%s\n'%name)

        path = map_settings['path']
        layer_settings  = map_settings['layers']
        sp = map_settings['startpos']
        gb = map_settings['bases']
        bgcolor = map_settings['bgcolor']
        self.layers = []
        for layer_setting in layer_settings:
            layer = self._createMap(layer_setting,path, startingPositions=sp,bases=gb,bgcolor=bgcolor)
            self.layers.append(layer)

        self.layers 


    def _createMap(self,mapConf,map_path,startingPositions=[],bases=[],bgcolor=(0,0,0)):
        ' Creates a map object using an hash from ini file ,map_path is the root dir of map files'
        W,H = string.split(mapConf["TileSize"],"x")
        W = int(W)
        H = int(H)
        map = self.__buildMap(os.path.join(map_path,mapConf['Map']))
        # load the tiles image
        tiles = load_image(os.path.join(map_path,mapConf['Tiles']), (255,0,255))

        game_map = GameMap(map,W,H,tiles,
                           startingPositions=startingPositions,
                           bases=bases,
                           bgcolor=bgcolor)
        return game_map

    def __buildMap(self,name):
        ''' build an 2d list array from a 8bit bmp using the index of the
            color as the value, dont use duplicate rgb values in index! 
        '''
        fullname = os.path.join('', name)
        try:
            image = pygame.image.load(fullname)
        except pygame.error, message:
            raise SystemExit(message)
        map = pygame.surfarray.array2d(image)
        return map



if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((640,480),HWSURFACE  )

    m =MapCreator(r'./Maps')
    m.getGameMap(m.maps.keys()[0])
    print m.getTiledLayer(0)
    print m.getAllMapNames()